package com.yzf.enterprise.framework.mybatisplus;

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import com.google.common.collect.Lists;
import com.yzf.enterprise.common.utils.ApiContext;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.schema.Column;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

import static com.yzf.enterprise.framework.mybatisplus.MybatisPlusTenantParser.TENANT_COLUMN;

@Configuration
@MapperScan("com.yzf.enterprise.mapper")
public class MybatisPlusConfig {

    private static final List<String> IGNORE_TENANT_TABLES = Lists.newArrayList();

    @Autowired
    private ApiContext apiContext;

    /**
     * 多租户属于 SQL 解析部分，依赖 MP 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        /*
         * 【测试多租户】 SQL 解析处理拦截器<br>
         * 这里固定写成住户 1 实际情况你可以从cookie读取，因此数据看不到 【 麻花藤 】 这条记录（ 注意观察 SQL ）<br>
         */
        List<ISqlParser> sqlParserList = new ArrayList<>();
        TenantSqlParser tenantSqlParser = new MybatisPlusTenantParser();
        tenantSqlParser.setTenantHandler(new TenantHandler() {

            /**
             * 2019-8-1
             *
             * https://gitee.com/baomidou/mybatis-plus/issues/IZZ3M
             *
             * tenant_id in (1,2)
             * @param  where 如果是where，可以追加，不是where的情况：比如当insert时，不能insert into enterprise(name, tenant_id) values('test', tenant_id IN (1, 2));
             * @return
             */
            @Override
            public Expression getTenantId(boolean where) {
//                final boolean multipleTenantIds = false;//这里只是演示切换单个tenantId和多个tenantId
//                //具体场景，可以根据情况来拼接
//                if (where && multipleTenantIds) {
//                    //演示如何实现tenant_id in (1,2)
//                    return multipleTenantIdCondition();
//                } else {
//                    //演示：tenant_id=1
//                    return singleTenantIdCondition();
//                }
                // 从当前系统上下文中取出当前请求的服务商ID，通过解析器注入到SQL中。（还可以从redis拿）

                Long currentProviderId = 1L;
                if (null == currentProviderId) {
                    throw new RuntimeException("getCurrentProviderId error.");
                }
                return new LongValue(currentProviderId);
            }

            private Expression singleTenantIdCondition() {
                return new LongValue(1L);
            }

            private Expression multipleTenantIdCondition() {
                final InExpression inExpression = new InExpression();
                inExpression.setLeftExpression(new Column(getTenantIdColumn()));
                final ExpressionList itemsList = new ExpressionList();
                final List<Expression> inValues = new ArrayList<>(1);

                inValues.add(new LongValue(1L));

                itemsList.setExpressions(inValues);
                inExpression.setRightItemsList(itemsList);
                return inExpression;
            }

            @Override
            public String getTenantIdColumn() {
                return TENANT_COLUMN;
            }

            @Override
            public boolean doTableFilter(String tableName) {
                // 忽略掉一些表：如租户表（provider）本身不需要执行这样的处理。
                return IGNORE_TENANT_TABLES.stream().anyMatch((e) -> e.equalsIgnoreCase(tableName));
            }
        });

        sqlParserList.add(tenantSqlParser);
        paginationInterceptor.setSqlParserList(sqlParserList);
        //paginationInterceptor.setSqlParserFilter(metaObject -> {
        //    MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);
        //    // 不使用租户信息
        //    if ("com.baomidou.springboot.mapper.UserMapper.selectListBySQL".equals(ms.getId())) {
        //        return true;
        //    }
        //    return false;
        //});
        return paginationInterceptor;
    }
}
